import { buffer, util } from '@kit.ArkTS';
import { socket } from '@kit.NetworkKit';
import { IOException } from '../Error/error';
import { Source } from './Source';

// 输入流
export class BufferedSource implements Source{
  _isGzip: boolean = false;
  set isGzip(value: boolean) {
    this._isGzip = value
  }
  private arraybuffer: ArrayBuffer;
  private uint8array: Uint8Array;
  private start: number = 0;     // 当前有效数据起始位置（已读部分）
  private end: number = 0;       // 当前有效数据结束位置（未读部分）
  rawSocket: socket.TCPSocket | socket.TLSSocket = null;
  private isClosed: boolean = false;
  private pendingReadLine: { resolve: (value: string | null) => void, reject: (reason?: any) => void ,limit: number} | null = null;
  private pendingRead: { resolve: (value: number | null) => void, reject: (reason?: any) => void ,sink: Uint8Array, byteCount: number} | null = null;
  private pendingReadHexadecimalUnsignedLong: { resolve: (value: number | null) => void, reject: (reason?: any) => void} | null = null;

  private readonly MIN_READ_CAPACITY = 1024;

  constructor(rawSocket: socket.TCPSocket | socket.TLSSocket | null, capacity: number = 8192) {
    if (rawSocket !== null && rawSocket !== undefined) {
      this.rawSocket = rawSocket
      this.rawSocket.on("message", (value:socket.SocketMessageInfo) => {
        console.log("testzhf response:: ",buffer.from(value.message).toString())
        if (this.isClosed) return;
        const newData = new Uint8Array(value.message);
        this.enqueue(newData);
      })
    }
    this.arraybuffer = new ArrayBuffer(capacity);
    this.uint8array = new Uint8Array(this.arraybuffer);
  }

  Stream(callback: (chunk: Uint8Array, complete?:  boolean, error?: Error) => void) {
    throw new Error('Method not implemented.');
  }

  readBytes(): Promise<Uint8Array> {
    throw new Error('Method not implemented.');
  }


  skipAll(): void {
    this.start = 0;     // 当前有效数据起始位置（已读部分）
    this.end = 0;       // 当前有效数据结束位置（未读部分）
  }

  /**
   * 🆕 静态方法：从 Uint8Array 创建 BufferedSource（同步数据源）
   */
  static fromBytes(data: Uint8Array): BufferedSource {
    const source = new BufferedSource(null, Math.max(data.length, 8192));
    source.enqueue(data);           // 写入数据
    source.isClosed = true;
    return source;
  }

  /**
   * 将新数据追加到缓冲区，必要时扩容
   */
  private enqueue(newData: Uint8Array): void {
    const required = this.end + newData.length;
    if (required > this.uint8array.length) {
      this.expandBuffer(required);
    }

    this.uint8array.set(newData, this.end);
    this.end += newData.length;
    // 👉 数据更新后，立即检查是否有挂起的 readline 请求可以完成
    this.tryFulfillPendingReadLine();
    this.tryFulfillPendingRead();
    this.tryFulfillPendingReadHexadecimalUnsignedLong();
  }

  /**
   * 尝试完成挂起的 readUtf8LineStrict 请求
   */
  private tryFulfillPendingRead(): void {
    if (!this.pendingRead) return;
    const { sink, byteCount } = this.pendingRead;
    const available = this.end - this.start;

    if (available >= byteCount) {
      // ✅ 数据现在足够了
      sink.set(this.uint8array.subarray(this.start, this.start + byteCount));
      this.start += byteCount;
      this.compact();
      this.pendingRead.resolve(byteCount);
      this.pendingRead = null;
    } else if (this.closed) {
      // ❌ 源已关闭，但数据仍不足
      this.pendingRead.reject(
        new IOException(`Failed to read ${byteCount} bytes: only ${available} bytes available and source is exhausted.`)
      );
      this.pendingRead = null;
    }
    // 仍然无法满足，继续等待
    // （什么也不做，pendingReadLine 保持不变）
  }

  private tryFulfillPendingReadHexadecimalUnsignedLong(): void {
    if (!this.pendingReadHexadecimalUnsignedLong) return;

    let result = 0;
    let foundHexChar = false; // 标记是否至少读取到一个十六进制字符
    while (this.start < this.end) {
      const b = this.uint8array[this.start];
      let value: number;

      // 解析十六进制字符
      if (b >= 0x30 && b <= 0x39) { // '0' - '9'
        value = b - 0x30;
      } else if (b >= 0x41 && b <= 0x46) { // 'A' - 'F'
        value = b - 0x41 + 10;
      } else if (b >= 0x61 && b <= 0x66) { // 'a' - 'f'
        value = b - 0x61 + 10;
      } else {
        // 遇到非十六进制字符，停止读取
        break;
      }

      // 检查是否溢出 (模拟 Long.MAX_VALUE)
      // 0x7fffffffffffffff 是 Long.MAX_VALUE
      if (result > (Number.MAX_SAFE_INTEGER - value) / 16) {
        return this.pendingReadLine.reject(new IOException('Number too large: hexadecimal value exceeds safe integer limit'))
      }

      result = result * 16 + value;
      this.start++;
      foundHexChar = true;
    }

    if (foundHexChar) {
      this.pendingReadHexadecimalUnsignedLong.resolve(result);
      this.pendingReadHexadecimalUnsignedLong = null;
      return;
    }else if (this.closed){
      // ❌ 源已关闭，但数据仍不足
      this.pendingRead.reject(
        new IOException(`Failed to read chunk bytes`)
      );
      this.pendingRead = null;
    }
    // 仍然无法满足，继续等待
    // （什么也不做，pendingReadLine 保持不变）
  }

  /**
   * 尝试完成挂起的 readUtf8LineStrict 请求
   */
  private tryFulfillPendingReadLine(): void {
    if (!this.pendingReadLine) return;

    // 查找 \r\n
    const lineEndIndex = this.indexOfCrlf();
    if (lineEndIndex !== -1) {
      const lineLength = lineEndIndex - this.start;
      if (lineLength > this.pendingReadLine.limit) {
        return this.pendingReadLine.reject(new IOException(`HTTP header line too large: ${lineLength} bytes (limit: ${this.pendingReadLine.limit})`));
      }
      const line = this.removeLine(lineEndIndex);
      this.pendingReadLine.resolve(line);
      this.pendingReadLine = null;
      return;
    }else if (this.closed){
      // ❌ 源已关闭，但数据仍不足
      this.pendingRead.reject(
        new IOException(`Failed to read Utf8Line bytes`)
      );
      this.pendingRead = null;
    }
    // 仍然无法满足，继续等待
    // （什么也不做，pendingReadLine 保持不变）
  }

  /**
   * 扩容缓冲区
   */
  private expandBuffer(minCapacity: number): void {
    const newCapacity = Math.max(this.uint8array.length * 2, minCapacity, this.MIN_READ_CAPACITY);
    const newBuffer = new ArrayBuffer(newCapacity);
    const newBuf = new Uint8Array(newBuffer);

    // 复制未读数据 [start, end)
    newBuf.set(this.uint8array.subarray(this.start, this.end), 0);
    this.end = this.end - this.start;
    this.start = 0;
    this.arraybuffer = newBuffer;
    this.uint8array = newBuf;
  }

  /**
   * 严格读取一行（以 \r\n 结尾），行长度不得超过 headerLimit
   * @param headerLimit 单行最大允许字节数（用于防止 OOM 攻击）
   * @returns 行字符串
   * @throws 如果行超长，或连接关闭且无完整行
   */
  readUtf8LineStrict(headerLimit: number = Number.MAX_VALUE): Promise<string> {
    return new Promise((resolve, reject) => {
      if (this.exhausted){
        return reject(new IOException('BufferedSource is exhausted'));
      }
      // 查找 \r\n
      const lineEndIndex = this.indexOfCrlf();
      if (lineEndIndex !== -1) {
        const lineLength = lineEndIndex - this.start;
        if (lineLength > headerLimit) {
          return reject(new IOException(`HTTP header line too large: ${lineLength} bytes (limit: ${headerLimit})`));
        }
        const line = this.removeLine(lineEndIndex);
        return resolve(line);
      }
      this.pendingReadLine = { resolve, reject, limit: headerLimit}
    });
  }

  async readString(): Promise<string>{
    throw new Error('Method not implemented.');
  }


  /**
   * 查找第一个 \r\n 的位置（相对于 start）
   * @returns 索引（相对于 buffer 开头），-1 表示未找到
   */
  private indexOfCrlf(): number {
    for (let i = this.start; i < this.end - 1; i++) {
      if (this.uint8array[i] === 0x0d && this.uint8array[i + 1] === 0x0a) { // \r\n
        return i;
      }
    }
    return -1;
  }


  async readHexadecimalUnsignedLong(): Promise<number> {
    return new Promise((resolve, reject) => {
      if (this.exhausted){
        return reject(new IOException('BufferedSource is exhausted'));
      }
      let result = 0;
      let foundHexChar = false; // 标记是否至少读取到一个十六进制字符
      while (this.start < this.end) {
        const b = this.uint8array[this.start];
        let value: number;

        // 解析十六进制字符
        if (b >= 0x30 && b <= 0x39) { // '0' - '9'
          value = b - 0x30;
        } else if (b >= 0x41 && b <= 0x46) { // 'A' - 'F'
          value = b - 0x41 + 10;
        } else if (b >= 0x61 && b <= 0x66) { // 'a' - 'f'
          value = b - 0x61 + 10;
        } else {
          // 遇到非十六进制字符，停止读取
          break;
        }

        // 检查是否溢出 (模拟 Long.MAX_VALUE)
        // 0x7fffffffffffffff 是 Long.MAX_VALUE
        if (result > (Number.MAX_SAFE_INTEGER - value) / 16) {
          return reject(new IOException('Number too large: hexadecimal value exceeds safe integer limit'))
        }

        result = result * 16 + value;
        this.start++;
        foundHexChar = true;
      }

      if (foundHexChar) {
        return resolve(result);
      }
      this.pendingReadHexadecimalUnsignedLong = { resolve, reject}
    });
  }
    /**
   * 提取并移除一行（不包含 \r\n）
   */
  private removeLine(lineEndIndex: number): string {
    const lineBytes = this.uint8array.subarray(this.start, lineEndIndex);
    const line = new util.TextDecoder().decodeToString(lineBytes);
    this.start = lineEndIndex + 2; // 跳过 \r\n
    this.compact();
    return line;
  }

  /**
   * 提取并移除所有剩余数据（用于最后不以 \r\n 结尾的情况）
   */
  private removeRemaining(): string {
    const lineBytes = this.uint8array.subarray(this.start, this.end);
    const line = new util.TextDecoder().decodeToString(lineBytes);
    this.start = this.end;
    this.compact();
    return line;
  }

  /**
   * 当 start 较大时，前移数据以腾出空间
   */
  private compact(): void {
    if (this.start > this.uint8array.length / 2) {
      this.uint8array.copyWithin(0, this.start, this.end);
      this.end = this.end - this.start;
      this.start = 0;
    }
  }

  /**
   * 实现 Source 接口
   */
  async read(sink: Uint8Array, byteCount: number): Promise<number> {
    if (this.exhausted) {
      return -1;
    }
    if (byteCount === 0) {
      return 0;
    }
    // 先尝试立即读取
    if (this.start < this.end) {
      const available = this.end - this.start;
      if (available >= byteCount) {
        // 数据足够，直接拷贝
        const subarray = this.uint8array.subarray(this.start, this.start + byteCount);
        sink.set(subarray);
        this.start += byteCount;
        this.compact();
        return byteCount;
      }
    }
    // 等待数据到达
    return new Promise((resolve, reject) => {
      if (this.isClosed) {
        return reject(new IOException('BufferedSource is closed'));
      }
      this.pendingRead = { resolve, reject, sink, byteCount };
    });
  }

  /**
   * 关闭 Source
   */
  close() {
    if (this.isClosed) return;
    this.isClosed = true;
    this.start = 0;     // 当前有效数据起始位置（已读部分）
    this.end = 0;       // 当前有效数据结束位置（未读部分）
  }

  SocketClose() {
    if (this.isClosed) return;
    this.isClosed = true;
    
    // 当 socket 关闭时，需要通知所有等待中的 Promise
    // 这样它们不会一直挂起直到超时
    const error = new IOException("Socket closed unexpectedly");
    
    if (this.pendingReadLine) {
      // 如果有足够的数据可以返回一行，先尝试返回
      const lineEnd = this.findLineBreak(this.pendingReadLine.limit);
      if (lineEnd !== -1) {
        const line = new util.TextDecoder('utf-8').decodeToString(this.uint8array.slice(this.start, lineEnd));
        this.start = lineEnd + 1;
        if (this.start < this.end && this.uint8array[this.start] === 0x0A) {
          this.start++;
        }
        this.compact();
        this.pendingReadLine.resolve(line);
      } else {
        // 没有完整的行，reject
        this.pendingReadLine.reject(error);
      }
      this.pendingReadLine = null;
    }
    
    if (this.pendingRead) {
      const available = this.end - this.start;
      if (available >= this.pendingRead.byteCount) {
        // 有足够数据，返回
        this.pendingRead.sink.set(this.uint8array.subarray(this.start, this.start + this.pendingRead.byteCount));
        this.start += this.pendingRead.byteCount;
        this.compact();
        this.pendingRead.resolve(this.pendingRead.byteCount);
      } else {
        this.pendingRead.reject(error);
      }
      this.pendingRead = null;
    }
    
    if (this.pendingReadHexadecimalUnsignedLong) {
      this.pendingReadHexadecimalUnsignedLong.reject(error);
      this.pendingReadHexadecimalUnsignedLong = null;
    }
  }
  
  /**
   * 查找行结束符的位置
   */
  private findLineBreak(limit: number): number {
    const searchEnd = Math.min(this.end, this.start + limit);
    for (let i = this.start; i < searchEnd; i++) {
      const b = this.uint8array[i];
      if (b === 0x0A || b === 0x0D) {
        return i;
      }
    }
    return -1;
  }


  /**
   * 获取缓冲区中未读数据长度
   */
  get bufferedSize(): number {
    return this.end - this.start;
  }

  /**
   * 是否已关闭
   */
  get closed(): boolean {
    return this.isClosed;
  }

  /**
   * 是否已读取完所有数据
   */
  get exhausted(): boolean {
    return this.closed && this.start === this.end;
  }

  get isEmpty(): boolean {
    return this.start === this.end;
  }

  buffer(): BufferedSource {
    return this;
  }

}
